<?php

namespace Hilaoyu\LaravelExtend\Services\AccessControl;

use Carbon\Carbon;
use Hilaoyu\LaravelExtend\ControllerBase;
use Hilaoyu\Utils\UtilHtml;
use Hilaoyu\Utils\UtilSupport;
use Illuminate\Http\Request;

abstract class AbstractControllerAccessControl extends ControllerBase
{

    abstract static protected function classNameEntityAccessControlEntities();
    abstract static protected function classNameEntityAccessControlRoles();
    abstract static protected function classNameEntityAuthUsers();

    public function entities(Request $request){
        //dd(boolval(0));
        $E_entities = UtilSupport::makeClass(static::classNameEntityAccessControlEntities());


        $search = [
            'keyword' => $request->input('keyword',''),
            'type' => $request->input('type',''),
        ];

        $models = $E_entities->select(function ($query) use ($search) {
            if ($search['type'] != '') {
                $query = $query->where('type', '=', trim($search['type']));
            }
            if(!empty($search['keyword'])){
                $query = $query->where(function ($query) use ($search){
                    $query->orWhere('id','like','%'. $search['keyword'] .'%')
                        ->orWhere('name','like','%'. $search['keyword'] .'%');
                });
            }

            return $query;
        }, ['id'=>'asc']);

        comResponse()->with($models, 'models');


        comResponse()->with( $search,'search')
            ->with($E_entities->buildTypeOptions($search['type'], '全部类型'), 'type_options');
        comResponse()->success();

        return $this->renderingResponse();
    }
    public function roles(Request $request){

        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());

        $search = [
            'keyword' => $request->input('keyword',''),
            'status' => $request->input('status',''),
        ];

        $models = $E_roles->select(function ($query) use ($search) {
            if ($search['status'] != '') {
                $query = $query->where('status', '=', $search['status']);
            }
            if(!empty($search['keyword'])){
                $query = $query->where(function ($query) use ($search){
                    $query->orWhere('id','like','%'. $search['keyword'] .'%')
                        ->orWhere('name','like','%'. $search['keyword'] .'%');
                });
            }

            return $query;
        }, ['id'=>'desc']);

        //UtilSupport::tryQuiet(function () use (&$models){
            $models->load(['accesses']);
            $models->each(function (&$item){
                $item->setAttribute('accesses_grouped',collect($item->getAttribute('accesses'))->groupBy('entity_id')->toArray());
                //return $item;
            });
        //});

        //dd($models->toArray());
        comResponse()->with($models, 'models');


        comResponse()->with( $search,'search')
            ->with(UtilHtml::statusOptions($search['status'], '是否启用'), 'status_options')
        ;
        comResponse()->success();

        return $this->renderingResponse();
    }


    public function roleSave(Request $request){
        $data = $request->only([
           'id',
           'name',
           'status',
        ]);
        $id = $request->input('origin_id','');
        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());

        $model = $E_roles->save($data, $id);
        //dd($model,$entity->getError());
        if ($model) {
            $new_id = $model->getKey();
            if($new_id != $id){
                //更新关联
                $model->accesses()->make()->where('role_id','=',$id)->update(['role_id'=>$new_id]);
            }

            comResponse()
                ->with($model, 'model')
                ->success('保存成功');
        }else{
            comResponse()
                ->failed('保存失败')
                ->withErrors($E_roles->getError());
        }

        return $this->renderingResponse();

    }

    public function roleDelete(Request $request){

        $id = $request->input('id', []);
        $id = (array)$id;
        if (empty($id)) {
            comResponse()->failed('参数错误');
            return $this->renderingResponse();
        }
        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());

        if ($E_roles->deleteMulti(function ($query) use ($id) {
            return $query->whereIn('id', $id);
        })
        ) {
            comResponse()->success('删除成功');
        } else {
            comResponse()->failed('删除失败')->withErrors($E_roles->getError());
        }

        return $this->renderingResponse();
    }

    public function roleAccesses(Request $request){

        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());
        $E_entities = UtilSupport::makeClass(static::classNameEntityAccessControlEntities());

        $role_id = $request->input('role_id','');
        $role = null;
        if($role_id ){
            $role = $E_roles->findById($role_id);
        }
        if($role){
            $role->clearOwnedAccessesCache();
        }

        $ownedAccesses = [];

        $accesses = $E_entities->select()->map(function ($item) use($role,&$ownedAccesses){
            /*$actions = collect($item::GetAllowActions($item->type))->map(function ($action_name,$action) use ($item,$role){
                return [
                    'name'=>$action_name,
                    'value' => $role->ownedAccesses($item->getKey(),$action),
                ];
            });*/
            $actions = collect($item::GetAllowActions($item->type));
            $actions->each(function ($action_name,$action) use ($item,$role,&$ownedAccesses){
                $ownedAccesses[$item->getKey()][$action] = $role->ownedAccesses($item->getKey(),$action,0);
            });

            $item->setAttribute('actions',$actions);
            return $item;
        });

        comResponse()->success()
            ->with($accesses,'accesses')
            ->with($ownedAccesses,'owned_accesses')
            ;

        return $this->renderingResponse();
    }
    public function roleAccessesSave(Request $request){

        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());
        $role_id = $request->input('role_id','');
        $accesses = $request->input('accesses',[]);
        $role = null;
        if(!$role_id || ! ($role = $E_roles->findById($role_id))){
            comResponse()->failed('参数错误');
            return $this->renderingResponse();
        }

        if($role->saveAccesses($accesses)){
            UtilSupport::tryQuiet(function ()use ($role){
                $role->clearOwnedAccessesCache();
            });
            comResponse()->success('保存成功');
        }else{
            comResponse()->failed('保存失败')->withErrors($role->getError());
        }



        return $this->renderingResponse();
    }


    public function users(Request $request){


        $E_user = UtilSupport::makeClass(static::classNameEntityAuthUsers());

        $search = [
            'keyword' => $request->input('keyword',''),
            'status' => $request->input('status',''),
            'role' => $request->input('role',''),
            'is_superuser' => $request->input('is_superuser',''),
        ];
        $withPager = intval($request->route('_with_pager'));
        if ($withPager > 0) {
            $pager = $this->getPager($withPager);
        } else {
            $pager = [
                'offset' => 0,
                'start' => 0,
                'page' => 0,
                'total' => null,
            ];
        }
        $models = $E_user->select(function ($query) use ($search) {
            if ($search['status'] != '') {
                if('1' == $search['status']){
                    $query = $query->where(function ($q){
                        return $q->orWhere('lock_to','<=',Carbon::now()->toDateTimeString())
                            ->orWhereNull('lock_to')
                            ;
                    });
                }else{
                    $query = $query->where('lock_to','>',Carbon::now()->toDateTimeString());
                }
            }
            if (1 == $search['is_superuser']) {
                $query = $query->whereHas('superuser');
            }
            if ($search['role'] != '') {
                $query = $query->whereHas('roles',function ($q) use ($search){
                    return $q->where('id', '=', $search['role']);
                });
            }
            if(!empty($search['keyword'])){
                $query = $query->where(function ($query) use ($search){
                    $query->orWhere('id','like','%'. $search['keyword'] .'%')
                        ->orWhere('name','like','%'. $search['keyword'] .'%');
                });
            }

            return $query;
        }, $request->route('_with_sort', ['name'=>'asc']), $pager['offset'], $pager['start'], $pager['total']);

        //UtilSupport::tryQuiet(function () use (&$models){
        $models->load(['roles','superuser']);

        $E_roles = UtilSupport::makeClass(static::classNameEntityAccessControlRoles());


        $roles = $E_roles->select(function ($query) {
            $query->where('status', '=', '1');
            return $query;
        }, ['name'=>'asc']);


        //dd($models->toArray());
        comResponse()->with($models, 'models');
        if ($withPager > 0) {
            comResponse()->withPager($pager);
        }

        comResponse()->with( $search,'search')
            ->with(UtilHtml::statusOptions($search['status'], '是否启用'), 'status_options')
            ->with(UtilHtml::formatHtmlOptions($roles->toArray(),'id','name','',$search['role']), 'role_options')
        ;
        comResponse()->success();

        return $this->renderingResponse();
    }

    public function userRolesSave(Request $request){
        $user_id = $request->input('user_id','');
        $role_ids = $request->input('role_ids',[]);

        $E_user = UtilSupport::makeClass(static::classNameEntityAuthUsers());
        $user = null;
        if(!$user_id || ! ($user = $E_user->findById($user_id))){
            comResponse()->failed('参数错误');
            return $this->renderingResponse();
        }

        if($user->saveRoles($role_ids)){
            //清除权限缓存
            UtilSupport::tryQuiet(function () use ($user){
                $user->clearOwnedAccessesCache();
            });
            comResponse()->success('保存成功');
        }else{
            comResponse()->failed('保存失败')->withErrors($user->getError());
        }
        return $this->renderingResponse();
    }

    public function superusersSave(Request $request){
        $user_id = $request->input('user_id','');

        $E_user = UtilSupport::makeClass(static::classNameEntityAuthUsers());
        $user = null;
        if(!$user_id || ! ($user = $E_user->findById($user_id))){
            comResponse()->failed('参数错误');
            return $this->renderingResponse();
        }

        if($user->saveSuperusers()){
            comResponse()->success('保存成功');
        }else{
            comResponse()->failed('保存失败')->withErrors($user->getError());
        }
        return $this->renderingResponse();
    }
    public function superusersDelete(Request $request){
        $user_id = $request->input('user_id','');

        $E_user = UtilSupport::makeClass(static::classNameEntityAuthUsers());
        $user = null;
        if(!$user_id || ! ($user = $E_user->findById($user_id))){
            comResponse()->failed('参数错误');
            return $this->renderingResponse();
        }

        if($user->deleteSuperusers()){
            comResponse()->success('保存成功');
        }else{
            comResponse()->failed('保存失败')->withErrors($user->getError());
        }
        return $this->renderingResponse();
    }
}
